package challenge;

import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;

/**
 *
 * Created by Tzachi on 18/10/2014.
 */
public class TangoInterview {
    /**
     * Add one item of the product with ID productdId to the shopping cart for the user identified by sessionId
     * shoppingCarts contains all shopping carts for all users
     * a shopping cart for a user is represented as a Vector<Long>
     * - each Long represents an individual item in a cart
     * - duplicates are ok and indicate that multiple items of the same product are in the cart
     * this method must succeed
     * exit criteria is that you have added the product to the shopping cart associated with the user
     * in a thread safe manner
     */

    public void addElement(String sessionId, Long productId, ConcurrentHashMap<String, Vector<Long>> shoppingCarts) {
        // sanity check
        if (sessionId == null || shoppingCarts == null) {
            return; // illegal call
        }
        // the vector before and after the needed update
        Vector<Long> oldVector, newVector;

        Vector<Long> onlyNewProduct = new Vector<>();
        onlyNewProduct.add(productId);
        do {
            oldVector = shoppingCarts.get(sessionId);
            // keep previous vector or create a new one
            if (oldVector == null) {
                newVector = new Vector<>();
            } else {
                newVector = new Vector<>(oldVector);
            }
            // anyway add the new product
            newVector.add(productId);

            // if putIfAbsent returns null -> there was no mapping for this entry at this point ->
            // we entered a new vector with only the new product -> done
            if (shoppingCarts.putIfAbsent(sessionId, onlyNewProduct) == null) {
                break;
            }
            // if putIfAbsent is not null -> there was a previous entry ->
            // we need to update it (oldVector should not be null anymore as well....)
        }
        while ((oldVector == null) || !shoppingCarts.replace(sessionId, oldVector, newVector));
        /**
         * If we reach here - updated is needed. We try to replace the previous vector with our new one
         *
         * Condition 1:
         * Old vector can still hold an old null value - loop again to retrieve
         * updated value - otherwise we will get a NullPointerException and also chance for wrong representation
         *
         * Condition 2:
         * If replace return false, it means someone changed the old vector in the map
         * We need to loop again to retrieve the updated value
         *
         * We keep iterating until at some point the oldVector won't change before replace it or
         * an putIfAbsent will take place. When the loop ends, we can be sure that we added the new
         * product to the shopping cart associated with the user
         */
    }
}
